package hehe.container;

import hehe.container.base.ResourcePath;
import hehe.container.base.context.AppContext;
import hehe.container.build.xml.tag.Tag;
import hehe.container.definition.BeanDefinition;
import hehe.container.definition.BeanDefinitionManger;
import hehe.container.scan.AnnotationScanHandler;
import hehe.container.scan.Scan;
import hehe.container.scan.ScanHandler;
import java.util.*;

/**
 * 容器类
 *<B>说明：</B>
 *<pre>
 * 提供单例对象创建
 *</pre>
 *<B>示例：</B>
 *<pre>
 *  略
 *</pre>
 *<B>日志：</B>
 *<pre>
 *  略
 *</pre>
 *<B>注意事项：</B>
 *<pre>
 *  略
 *</pre>
 */
public class Container
{
    /**
     * 当前容器对象
     *<B>说明：</B>
     *<pre>
     *  一个应用只能有一个
     *</pre>
     */
    protected static Container container;

    /**
     * 应用上下文
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected AppContext appContext = new AppContext();

    /**
     * 扫描列表
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    protected List<Scan> scans = new ArrayList<>();

    /**
     * bean 定义管理类
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected BeanDefinitionManger beanDefinitionManger = new BeanDefinitionManger();

    /**
     * 资源路径
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected ResourcePath resourcePath = new ResourcePath();

    public Container()
    {
        container = this;

    }


    /**
     * 获取当前容器
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @return Container
     */
    public static  Container getContainer()
    {
        if (container == null) {
            new Container();
        }

        return container;
    }

    /**
     * 获取bean 定义管理类
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public BeanDefinitionManger getBeanDefinitionManger()
    {
        return this.beanDefinitionManger;
    }

    public ResourcePath getResourcePath()
    {
        return this.resourcePath;
    }

    /**
     * 获取bean 实例
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @param beanId beanId
     */
    public  <T> T getBean(String beanId)
    {
        try {
            if (this.beanDefinitionManger.hasBeanDefinition(beanId)) {
                BeanDefinition beanDefinition = this.beanDefinitionManger.getBeanDefinition(beanId);
                if (beanDefinition.isSingleton() && this.appContext.hasBean(beanId)) {
                    return (T)this.appContext.getBean(beanId);
                }
                // 开始创建对象
                Object bean = beanDefinition.make();
                // 判断是否单例
                if (beanDefinition.isSingleton()) {
                    this.appContext.setBean(beanId,bean);
                }

                return (T)bean;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 根据属性创建创建对象
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    public  <T> T getBean(Map<String,Object> attrs)
    {
        BeanDefinition beanDefinition = new BeanDefinition(attrs);
        try {
            return (T)beanDefinition.make();
        } catch (Exception ex) {
            return null;
        }
    }

    /**
     * 创建bean 对象
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    public  <T> T makeBean(String beanid)
    {
        BeanDefinition beanDefinition = new BeanDefinition(beanid);
        try {
            return (T)beanDefinition.make();
        } catch (Exception ex) {
            return null;
        }
    }


    /**
     * 注册扫描
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    public void registerScan(Scan scan)
    {
        this.scans.add(scan);
    }

    /**
     * 开始扫描
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    public void doScan()
    {
        for (Scan scan:this.scans) {
            scan.registerHandler(new AnnotationScanHandler());
            try {
                List<Class<?>> clazzs = scan.scanPackage();
                List<ScanHandler> handlers = scan.getHandlers();
                for (ScanHandler handler:handlers) {
                    handler.handler(clazzs);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
